﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace StatelyCompiler
{
    public class Token
    {
        public int LineNumber { get; private set; }
        public int ColumnNumber { get; private set; }

        public enum TokenType { OpenBrace, CloseBrace, State, TransitionTo, Derail, Wildcard, Pipe, Break }

        internal static Token ForStartState(string stateName, int colNum, int lineNum)
        {
            Token token = For(TokenType.State, stateName, colNum, lineNum);

            token.IsStartState = true;

            return token;
        }

        internal static Token For(TokenType tokenType, string data, int colNum, int lineNum)
        {
            if (tokenType == TokenType.State &&
                string.IsNullOrWhiteSpace(data)) throw new InvalidOperationException("Data required to build State token");

            Token token = new Token();

            token.Kind = tokenType;
            token.Data = data;
            token.IsStartState = false;
            token.IsCompletionState = false;
            token.IsArrayState = false;
            token.ColumnNumber = colNum;
            token.LineNumber = lineNum;

            return token;
        }

        internal static Token For(TokenType tokenType, int colNum, int lineNum)
        {
            return For(tokenType, tokenType == TokenType.Pipe ? "|" : (tokenType == TokenType.Wildcard ? "*" : null), colNum, lineNum);
        }

        internal static Token ForCompletionState(string stateName, int colNum, int lineNum)
        {
            Token token = For(TokenType.State, stateName, colNum, lineNum);

            token.IsCompletionState = true;

            return token;
        }

        internal static Token ForArrayState(string stateName, int colNum, int lineNum)
        {
            Token token = For(TokenType.State, stateName, colNum, lineNum);

            token.IsArrayState = true;

            return token;
        }

        public TokenType Kind { get; private set; }

        public string Data { get; set; }

        public bool IsStartState { get; private set; }
        
        public bool IsArrayState { get; private set; }
        
        public override string ToString()
        {
            if (Kind == Token.TokenType.State)
            {
                string specialState = IsStartState ? "(Starting State)" : (IsCompletionState ? "(Completion State)" : "");

                return "{0}{1} {2}".F(Data, specialState, "l:{0} c:{1}".F(LineNumber, ColumnNumber));

            }
            else
            {
                return "* {0} {1}".F(Kind.ToString(), "l:{0} c:{1}".F(LineNumber, ColumnNumber));
            }
        }

        public bool IsCompletionState { get; set; }        
    }
}
